#ifndef CELL_H
#define CELL_H

#include <QVector>
#include <QtCore>
#include "metal.h"
#include "strap.h"
#include "via.h"
#include "transistor.h"

class Cell
{
    friend class MainWindow;
    friend class Placement;
    friend class Data;
    friend class Routing;
    friend class Routing1;
    friend class Routing2;
    friend class TAPlacement;

    QList<Metal*> *metalItems;
    QList<Metal*> *m1Items;
    QList<Metal*> *m2Items;
    QList<Metal*> *m1PinItems;
    QList<Metal*> *poItems;
    QList<Metal*> *diffItems;
    QList<Metal*> *coItems;

    QList<Via*> *vias;

    QStringList pins;
    QString cellName;


    Metal* gndRectItem;
    Metal* nWellRectItem;
    Metal* nPlusRectItem;
    Metal* pPlusRectItem;

    Strap *vccStrapItem;
    Strap *gndStrapItem;

    bool alreadyPlaced;

    //SIZE Constraints
    qreal gndHeight;
    qreal vccHeight;
    qreal pmosHeight;
    qreal nmosHeight;

    qreal maxX;
    qreal minX;

    void setTransistorYPosition(Transistor* t);
    void setTransistorYPosition();
    void setTransistorsScenePosition();
    Transistor *getTransistorByPosIndex(QList<Transistor *> *transistors, Transistor *curT);
    Transistor *getTransistorByPosIndex(QList<Transistor *> *transistors, int posIndex);
    boolean hasContact(Transistor *t);
    boolean hasGap(Transistor* t,  QList<Transistor*> *transistors );
    QString getLeftNet(Transistor* t);
    int countContacts(Transistor *tr, QList<Transistor *> *transistors);
    void setInitialScenePositions(QList<Transistor *> *t);
    void setInitialScenePositions();
    void fixVerticalAlignment();
    void fixVerticalAlignment(QList<Transistor *> *collT1, QList<Transistor *> *collT2);
    void translateTransistors(QList<Transistor *> *transistors, int startIndex, float dx);
    void setMaxX();
    void setVccGndPosition();
    void setPPlusPosition();
    void setNPlusPosition();
    void setNWellPosition();
    void setVccGndStraps();
    void fixPositions();
    void sortByGateNetName();
    void sortByPosIndex();

    void mergeTransistors(QList<Transistor *> *transistors);
    void mergeTransistors();
    void folding();
    void resetContacts();

    QGraphicsScene* getM1Scene();
    QStringList *getGateNets();

public:
    QList<Transistor*> *nTransistors;
    QList<Transistor*> *pTransistors;
    Metal* vccRectItem;

    QString removeOutSideRoutedM1();

    Cell();
    QString getCellName() const;
    void addTransistor(Transistor *t);
    void setCellName(QString name);
    void addPin(QString pin);
    void refreshScenePositions();
    void addItemsToScene(QGraphicsScene* scene);
    void setShowLabel(bool showLabels);
    QString toString();

    qreal getPmosGateMaxY(QString net);
    qreal getNmosGateMinY(QString net);
    qreal getNmosGateMaxY(QString net);
    qreal getPmosGateMinY(QString net);

    void exportAsCif(QString fileName);

    void reset();

    QString getCellSize();

    void recursiveRemoveTransistor(QList<Transistor *> *transistors);
    void folding(QList<Transistor *> *transistors);

    void releaseMemory();
    void releaseMemory(QList<Metal *> *items);
    void releaseMemory(QList<Transistor *> *transistors);
    Metal *getVccStrapBlockingPoly();
    Metal *getGndStrapBlockingPoly();
};
#endif // CELL_H
